package im.agents.service;

import java.util.HashMap;
import java.util.Map;

import jade.core.AID;
import jade.core.Location;
import jade.domain.FIPANames;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.domain.FIPANames.InteractionProtocol;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.proto.AchieveREInitiator;
import im.agents.IMAgent;
import im.agents.contextmanager.GetAgentContextResponder;
import im.agents.migration.BestLocationRequester;
import im.agents.migration.ContextDataRequester;
import im.agents.migration.ContextMonitoring;
import im.agents.utility.Utility;
import im.domain.Context;
import im.domain.SLA;
import im.domain.XMLSerializer;

public abstract class ServiceProvider extends IMAgent {
	
	Context context;
	private Map<String, SLA> subscribedSLAs = new HashMap<String, SLA>();
	private Map<String, AID> slaCheckers = new HashMap<String, AID>();
	 public Map<String, SLA> getSubscribedSLAs() {
	  return subscribedSLAs;
	 }
	
	 public void setSubscribedSLAs(Map<String, SLA> subscribedSLAs) {
	  this.subscribedSLAs = subscribedSLAs;
	 }
	

	@Override
	public ServiceDescription getServiceDescription() {
		ServiceDescription service = new ServiceDescription();
		service.setName("X");
		service.setType("X");
		return service;
	}
	
	/* (non-Javadoc)
	 * @see im.agents.IMAgent#setup()
	 * Ricorda di ripristinare la migrazione!!!!!
	 */
	public void setup(){
		super.setup();
		this.initializeTHRESHOLD(2, 5, 5);//mettere valori sensati
		MessageTemplate mt = MessageTemplate.MatchProtocol(
				InteractionProtocol.FIPA_CONTRACT_NET);
		mt=MessageTemplate.and(mt, 
				MessageTemplate.MatchPerformative(ACLMessage.CFP));
		addBehaviour(new NegotiateSLAResponder(this,mt));
		addBehaviour(new ContextMonitoring(this,20000,this.getTHRESHOLD()));
		//setContext();
		addBehaviour(new GetAgentContextResponder(this));
		
	}
	
/*	private void setContext() {
		DFAgentDescription context_ds = Utility.findAgent(this, "context-info");
		if(context_ds== null){
			System.out.println("ContextManager not found");
		}else {
			ACLMessage request2 = new ACLMessage(ACLMessage.REQUEST);
			request2.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
			request2.setSender(this.getAID());
			//request2.setContent(XMLSerializer.doSerialize(((IMAgent)myAgent).getTHRESHOLD()));
			request2.addReceiver(context_ds.getName());
			this.addBehaviour(new AchieveREInitiator(this,request2){
				protected void handleInform(ACLMessage inform){
					//XMLSerializer serializer = new XMLSerializer();
					context = (Context) XMLSerializer.doDeserialize(inform.getContent());
					//System.out.println("SONO IL CONTEXT REQUESTER ricevuta risposta da"+inform.getSender());
				}
			});
		}
		
	}*/

	public void takeDown(){
		super.takeDown();
		//TODO
	}
	
	protected void afterMove() {
		super.afterMove();
		
		//trovo il monitor del nuovo nodo
		DFAgentDescription monitor_ds = Utility.findAgent(this, "monitor");
		
		//per ogni SLA sottoscritto
		for(String slaId : getSubscribedSLAs().keySet()){
			ACLMessage notifySLAChecker = new ACLMessage(ACLMessage.INFORM_IF);
			notifySLAChecker.setConversationId(slaId);
			System.out.println("["+getLocalName()+"] " +
					"Informo SC ("+slaCheckers.get(slaId).getLocalName()+") che sono migrato. " +
					"Nuovo monitor == "+monitor_ds.getName().getLocalName());
			notifySLAChecker.addReceiver(slaCheckers.get(slaId)); //informo l'SLAChecker competente
			notifySLAChecker.setContent(
					XMLSerializer.doSerialize(monitor_ds.getName())); //e gli comunico l'AID del nuovo monitor
			send(notifySLAChecker);
		}
		
	}

	public abstract SLA getSLAProposal(String serviceName);

	public Map<String, AID> getSlaCheckers() {
		return slaCheckers;
	}

	public void setSlaCheckers(Map<String, AID> slaCheckers) {
		this.slaCheckers = slaCheckers;
	}


}
